#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int words;
int bytes;
int lines;

/*
int count(char c, int last_char)
{
	int ret = 0;
	switch (c)
	{
		case ' ':
		case '\t':	
			ret = 1;
			break;
		case '\n':		
			++lines;
			ret = 1;
			break;
		default:
			if (last_char)
				++words;
			break;
	}
	++bytes;
	return ret;
}

void wc(int fd)
{
	char c;
	int last_char;
	last_char = 1;
	while (read(fd, &c, 1) > 0) {
		last_char = count(c, last_char);
	}
}
*/
int count(char, int);
void wc(int fd);

void print_help(){
	fprintf(stdout, 
	"Usage:\n"
	"tp1 -h\n"
	"tp1 -V\n"
	"tp1 [options] [file...]\n"
	"Options:\n"
	"-v, --version Print version and quit.\n"
	"-h, --help Print this information and quit.\n"
	"-w, --words Print the number of words.\n"
	"-l, --lines Print the number of lines.\n"
	"-c, --bytes Print the number of bytes.\n");
}

void print_version(){
	fprintf(stdout, "Version 1.0\n");
}

void print(int options, char* filename) {
	char separador = ' ';

	if (filename == 0) {
		separador = '\t';
		if (options != 1 || options != 2 || options != 4)
			printf("%c", separador);
	}

	switch (options) {
		case 0:
		case 7:
			printf("%d%c%d%c%d", lines, separador, words, separador, bytes);
			break;
		case 1:
			printf("%d", words);
			break;
		case 2:
			printf("%d", lines);
			break;
		case 3:
			printf("%d%c%d", lines, separador, words);
			break;
		case 4:
			printf("%d", bytes);
			break;
		case 5:
			printf("%d%c%d", words, separador, bytes);
			break;
		case 6:
			printf("%d%c%d", lines, separador, bytes);
			break;
		default:
			break;
	}

	if (filename != 0)
		printf(" %s\n", filename);
	else
		printf("\n");		
}

void print_total(int options, int lines, int words, int bytes) {
	printf("\t%d\t%d\t%d\ttotal", lines, words, bytes);
}

void reset() {
	lines = 0;
	bytes = 0;
	words = 0;
}

int main(int argc, char** argv) {
	int total_lines = 0;
	int total_bytes = 0;
	int total_words = 0;
	extern int optind, opterr, optopt;
	/* Una cadena que lista las opciones cortas válidas */
	const char* const opcionesCortas = "wlcvh";
	int options = 0;
	int i, fd, c;
	/* Una estructura de varios arrays describiendo las opciones largas */
	const struct option opcionesLargas[] = {
	  { "help",	  no_argument, NULL,'h'},
	  { "version", no_argument, NULL,'v'},
	  { "words",no_argument, NULL,'w'},
	  { "lines",no_argument, NULL,'l'},
	  { "bytes",no_argument, NULL,'c'},
	  { NULL,     no_argument, NULL, 0 }
	};

	opterr = 0;

	while ((c = getopt_long(argc, argv, opcionesCortas, opcionesLargas, NULL)) != -1)
	 switch (c)
	   {
	   case 'w':
	     options += 1;
	     break;
	   case 'l':
	     options += 2;
	     break;
	   case 'c':
	     options += 4;
	     break;
	   case 'h':
	     print_help();
	     exit(EXIT_SUCCESS);
	   case 'v':
	     print_version();
	     exit(EXIT_SUCCESS);
	   case '?':
	     fprintf (stderr, "Unknown option character\n");
	     print_help();
	     exit(EXIT_FAILURE);
	   default:
	     abort ();
	   }
	
	if(optind == -1 || optind == argc)
    	{
		reset();
        	wc(STDIN_FILENO);
		print(options, STDIN_FILENO);
    	}
    	else
    	{
        	for(i=optind; i<argc; ++i)
        	{			
			reset();
            		fd = open(argv[i], O_RDONLY);
    			if( fd == -1)
        			fprintf(stderr, "%s: No such file or directory\n", argv[i]);
			else {
	    			wc(fd);
				print(options, argv[i]);
    				close(fd);
				total_lines += lines;
				total_bytes += bytes;
				total_words += words;
			}		
			
        	}
		if (argc - optind > 1) {
			lines = total_lines;
			words = total_words;
			bytes = total_bytes;
			print(options, "total");
		}
    	}
	return 0;
}

